#include "graphics/gl/ooglrender.h"
#include "graphics/ootexture.h"
#include <gl/glut.h>

#ifndef APIENTRY
#   define APIENTRY
#endif
//! Function to perform extentsions initialisation.
void initialiseGLExtensions();
//! Pointer to a function to use as glActiveTexture
PFNGLACTIVETEXTUREPROC g_activeTexture;
//! Pointer to a function to use as glClientActiveTexture
PFNGLCLIENTACTIVETEXTUREPROC g_clientActiveTexture;
//! Dummy function for if real ones are not present (saves testing each render)
void APIENTRY activeTextureDummy(GLenum) {}

//------------------------------------------------------------------------
ooGLRender::ooGLRender()
:m_begined(false)
{
	initialiseGLExtensions();
}

//------------------------------------------------------------------------
ooGLRender::~ooGLRender()
{

}

//------------------------------------------------------------------------
void 
ooGLRender::tick( float elapsed )
{
	glGetIntegerv(GL_VIEWPORT, m_vp);
	glClearColor(1,1,0,1);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
}

//------------------------------------------------------------------------
void 
ooGLRender::bindTexture( Ptr<ooTexture> texture )
{
	glBindTexture(GL_TEXTURE_2D,texture->getTextureId());
}

//------------------------------------------------------------------------
void
ooGLRender::focusWindow(ooDisplayWindow* window)
{
	m_focus = window;
}

//------------------------------------------------------------------------
void 
ooGLRender::render2DPrimitivesGroup( const oo2DPrimitivesGroup* group )
{

}

//------------------------------------------------------------------------
void
ooGLRender::begin2D()
{
	dbbassert(!m_begined);
	m_begined	= true;

	glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
	glPushAttrib(GL_ALL_ATTRIB_BITS);

	g_activeTexture(GL_TEXTURE0);
	g_clientActiveTexture(GL_TEXTURE0);

	glPolygonMode(GL_FRONT, GL_FILL);
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0.0f, m_vp[2], 0, m_vp[3]);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_FOG);
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	glDisable(GL_TEXTURE_GEN_R);

	glFrontFace(GL_CCW);
	glCullFace(GL_BACK);
	glEnable(GL_CULL_FACE);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glEnable(GL_TEXTURE_2D);
}

void ooGLRender::end2D()
{
	dbbassert(m_begined);

	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);

	//restore former attributes
	glPopAttrib();
	glPopClientAttrib();

	m_begined	= false;
}

//------------------------------------------------------------------------
void 
ooGLRender::present()
{
	glutSwapBuffers();
}

//----------------------------------------------------------------------------//
void 
initialiseGLExtensions()
{
	// initialise GLEW
	GLenum err = glewInit();
	if (GLEW_OK != err)
	{
		LogError("initialise gl extensions failed!");
	}

	// GL 1.3 has multi-texture support natively
	if (GLEW_VERSION_1_3)
	{
		g_activeTexture			= glActiveTexture;
		g_clientActiveTexture	= glClientActiveTexture;
	}
	// Maybe there is the ARB_multitexture extension version?
	else if (GL_ARB_multitexture)
	{
		g_activeTexture			= glActiveTextureARB;
		g_clientActiveTexture	= glClientActiveTextureARB;
	}
	// assign dummy functions if no multitexture possibilities
	else
	{
		g_activeTexture			= activeTextureDummy;
		g_clientActiveTexture	= activeTextureDummy;
	}
}